import * as THREE from 'three';
import Hammer from 'hammerjs';
import Model from './model' 
import Ray from './ray'
import Preloader from './preloader'

export default class Controls{
    // 01: Build controller
    constructor() {
        console.log('控制器类')
        // User viewing modes
        this.introComplete = false; // Tracks intro or main view 介绍界面或主界面
        this.modeOrbit = false; // Uses gyro to orbit camera
        // Device features
        this.deviceTouch = undefined; // Is it a touch device // 触摸事件
        this.deviceAccel = false; // Does it have accelerometer data? // 是否有加速设备
        this.zoom = 1;
        TweenLite.defaultEase = Power2.easeInOut;
        this.pageMain = document.getElementById("pageMain");
        this.model = new Model(this.pageMain); // 设置场景
        this.mouseTap = new THREE.Vector2(1000, 1000);
        // Check if it's touch device
        this.hammer = new Hammer(this.pageMain);
        this.refHammerPan = this.rippleTouch.bind(this);
        this.hammer.get("pan").set({ direction: Hammer.DIRECTION_ALL, threshold: 3 });
        this.hammer.on("hammer.input", this.refHammerPan);
        window.addEventListener("resize", this.onWindowResize.bind(this), false);

        this.ray = new Ray(this.model.monoc.camera);
        this.preload();
    }
    /////////////////////////////////////// INTRO SEQUENCE ////////////////////////////////////////
    // 02: Start asset preload 预加载资源
    preload = function () {
        var manifesto = [
            // Cube textures
            { name: "envReflection", type: "cubetexture", ext: "jpg" }, // 远处环境
            { name: "envSkybox", type: "cubetexture", ext: "jpg" }, // 天空场景
            // Car lights
            { name: "flareHead", type: "texture", ext: "jpg" },
            { name: "flareTurn", type: "texture", ext: "jpg" },
            { name: "lightTurn", type: "texture", ext: "jpg" },
            { name: "lightStop", type: "texture", ext: "jpg" },
            // Car geometry
            { name: "vrBodyCompiled", type: "mesh", ext: "json" }, // 车体
            { name: "vrWheelBrakes", type: "mesh", ext: "json" }, // 轮胎
            // Other
            { name: "thread", type: "texture", ext: "jpg" }, // 车轮纹
            { name: "shadow", type: "texture", ext: "jpg" }, // 影子
            { name: "icoBtns", type: "texture", ext: "png" },
            { name: "icoCtrls", type: "texture", ext: "png" },
        ];
        var path = "/dist/images/3d/";
        this.preloader = new Preloader(path, manifesto, this);
        window["preloader"] = this.preloader;
        this.preloader.start();
        this.model.introPreloading();
    };
    // 03: Preloading has completed, wait for input 预加载结束、新建车辆天空等、进入引导页、等待点击事件
    preloadComplete = function (_cargo) {
        this.model.introPreloaded(_cargo);
        this.introComplete = true;
        // Create tap listener
        this.refHammerTap = this.introAnimation.bind(this);
        this.hammer.on("tap", this.refHammerTap);
    };
    // 04: Tap received, play intro animation 点击引导页，切换摄像头角度，移除预加载页面
    introAnimation = function (evt) {
        // Determines touch device
        if (typeof this.deviceTouch === "undefined") {
            this.hammerCheckTouch(evt);
        }
        // Remove intro hammer listeners
        this.hammer.off("tap", this.refHammerTap);
        this.hammer.off("hammer.input", this.refHammerPan);
        // 引导页切换动画
        this.model.introStart();
        this.preloader.remove();
        // 延迟3秒，初始化控制页面
        TweenLite.delayedCall(3.0, this.initControls.bind(this));
    };
    // 05: Intro animation complete, initiate controls 引导页动画结束后，初始化控制器
    initControls = function (evt) {
        // 初始化键盘事件
        this.initKeyboard();
        // 初始化触摸手势事件
        this.initHammer();
    };
    
    /////////////////////////////////////// HAMMER CONTROLS ////////////////////////////////////////
    // Raycasts for ripples
    rippleTouch = function (evt) {
        if (evt.isFinal === false) {
            this.raycast(evt);
        }
    };
    // Checks if it's touch or mouse
    hammerCheckTouch = function (evt) {
        switch (evt.pointerType) {
            case "mouse":
                this.deviceTouch = false;
                break;
            case "touch":
            default:
                this.deviceTouch = true;
                break;
        }
    };
    initHammer = function () {
        if (this.deviceTouch) {
            // Enables pinch & controls
            this.hammer.get("pinch").set({ enable: true });
            this.hammer.on("pinchstart", this.hammerPinchStart.bind(this));
            this.hammer.on("pinch", this.hammerPinch.bind(this));
        }
        else {
            // Enables camera orbit controls
            this.hammer.get("pan").set({ direction: Hammer.DIRECTION_ALL, threshold: 1 });
            this.hammer.on("pan", this.hammerPan.bind(this));
        }
    };
    hammerPan = function (event) {
        this.model.cam.orbitBy(event.velocityX, event.velocityY);
    };
    hammerPinchStart = function (event) {
        this.zoom = this.model.cam.distTarget;
    };
    hammerPinch = function (event) {
        this.model.cam.distTarget = this.zoom / event.scale;
    };

    raycast = function (event) {
        this.mouseTap.x = (event.pointers[0].clientX / this.model.vpW) * 2 - 1;
        this.mouseTap.y = (event.pointers[0].clientY / this.model.vpH) * -2 + 1;
        var pos = this.ray.rayCast(this.mouseTap);
        if (typeof pos !== "boolean") {
            this.model.grid.moveRippleOrigin(pos.x, pos.z);
        }
    };
    /////////////////////////////////////// KEYBOARD CONTROLS ////////////////////////////////////////
    initKeyboard = function () {
        window.addEventListener("keydown", this.model.props.onKeyDown.bind(this.model.props), false);
        window.addEventListener("keyup", this.model.props.onKeyUp.bind(this.model.props), false);
    };
    
    /////////////////////////////////////// WINDOW EVENTS ////////////////////////////////////////
    // User scrolls down 鼠标滚轮事件
    gestureWheel = function (event) {
        // Dolly cam
        switch (event.deltaMode) {
            case 0:
                this.model.cam.dolly(event.deltaY * 0.2);
                break;
            case 1:
                this.model.cam.dolly(event.deltaY * 20);
                break;
            case 2:
                this.model.cam.dolly(event.deltaY * 40);
                break;
        }
    };
    // Browser window resize 
    onWindowResize = function () {
        this.model.onWindowResize();
    };
    update = function (t) {
        if (this.introComplete === false) {
            this.model.updateIntro(t);
        }
        else {
            this.model.update(t, false);
        }
    };
}